import {ScannerResult} from "../../types";
import path from "path";
import fs from "fs-extra";
import folderSize from "../../utils/folderSize";
import {XmlUtil} from "../../utils/XmlUtil";
import {FormatUtil} from "../../utils/FormatUtil";

// Java依赖信息
export interface JavaDependency {
  groupId: string;
  artifactId: string;
  version: string;
  scope?: string;
}

// Java项目信息
export interface JavaProjectInfo {
  groupId?: string;
  artifactId?: string;
  version?: string;
  dependencies: JavaDependency[];
}

/**
 * 从POM XML中提取Maven依赖信息
 */
function extractMavenDependencies(pomXml: string): JavaDependency[] {
  const dependencies: JavaDependency[] = [];

  // 使用正则表达式匹配所有依赖
  const dependencyRegex = /<dependency>[\s\S]*?<\/dependency>/g;
  const dependencyMatches = pomXml.match(dependencyRegex) || [];

  for (const depXml of dependencyMatches) {
    const groupId = XmlUtil.getTagValue(depXml, 'groupId');
    const artifactId = XmlUtil.getTagValue(depXml, 'artifactId');
    const version = XmlUtil.getTagValue(depXml, 'version');
    const scope = XmlUtil.getTagValue(depXml, 'scope');

    if (groupId && artifactId) {
      dependencies.push({
        groupId,
        artifactId,
        version: version || '',
        scope
      });
    }
  }

  return dependencies;
}

/**
 * 扫描Maven项目
 */
async function scanMavenProject(projectPath: string): Promise<JavaProjectInfo | null> {
  try {
    const pomPath = path.join(projectPath, 'pom.xml');

    if (!await fs.pathExists(pomPath)) {
      return null;
    }

    const pomXml = await fs.readFile(pomPath, 'utf-8');

    const groupId = XmlUtil.getTagValue(pomXml, 'groupId');
    const artifactId = XmlUtil.getTagValue(pomXml, 'artifactId');
    const version = XmlUtil.getTagValue(pomXml, 'version');
    const dependencies = extractMavenDependencies(pomXml);

    return {
      groupId,
      artifactId,
      version,
      dependencies
    };
  } catch (error) {
    console.error(`扫描Maven项目失败: ${projectPath}`, error);
    return null;
  }
}

/**
 * 解析Gradle构建文件中的依赖
 */
function extractGradleDependencies(buildGradle: string): JavaDependency[] {
  const dependencies: JavaDependency[] = [];

  // 查找依赖声明
  const depsRegex = /dependencies\s*\{[\s\S]*?\}/g;
  const depsBlocks = buildGradle.match(depsRegex) || [];

  for (const block of depsBlocks) {
    // 匹配依赖声明，如: implementation 'com.example:library:1.0.0'
    const depRegex = /(implementation|api|compile|testImplementation|androidTestImplementation)\s+['"]([^:'"]+):([^:'"]+)(?::([^'"]+))?['"]/g;
    let match;

    while ((match = depRegex.exec(block)) !== null) {
      const scope = match[1];
      const groupId = match[2];
      const artifactId = match[3];
      const version = match[4] || '';

      dependencies.push({
        groupId,
        artifactId,
        version,
        scope
      });
    }
  }

  return dependencies;
}

/**
 * 扫描Gradle项目
 */
async function scanGradleProject(projectPath: string): Promise<JavaProjectInfo | null> {
  try {
    const buildGradlePath = path.join(projectPath, 'build.gradle');

    if (!await fs.pathExists(buildGradlePath)) {
      return null;
    }

    const buildGradle = await fs.readFile(buildGradlePath, 'utf-8');

    // 尝试从构建文件中提取项目信息
    const groupIdMatch = buildGradle.match(/group\s*=\s*['"]([^'"]+)['"]/);
    const versionMatch = buildGradle.match(/version\s*=\s*['"]([^'"]+)['"]/);
    const artifactIdMatch = buildGradle.match(/rootProject\.name\s*=\s*['"]([^'"]+)['"]/);

    const groupId = groupIdMatch ? groupIdMatch[1] : undefined;
    const version = versionMatch ? versionMatch[1] : undefined;
    let artifactId = artifactIdMatch ? artifactIdMatch[1] : undefined;

    // 如果在构建文件中找不到artifactId，则使用目录名
    if (!artifactId) {
      artifactId = path.basename(projectPath);
    }

    const dependencies = extractGradleDependencies(buildGradle);

    return {
      groupId,
      artifactId,
      version,
      dependencies
    };
  } catch (error) {
    console.error(`扫描Gradle项目失败: ${projectPath}`, error);
    return null;
  }
}

/**
 * 对依赖进行分类
 */
function categorizeDependencies(dependencies: JavaDependency[]): Record<string, JavaDependency[]> {
  const categorized: Record<string, JavaDependency[]> = {
    compile: [],
    runtime: [],
    test: [],
    provided: [],
    system: [],
    other: []
  };

  // 对依赖进行分类
  for (const dep of dependencies) {
    const scope = dep.scope?.toLowerCase() || 'compile';
    if (scope === 'compile' || scope === 'implementation' || scope === 'api') {
      categorized.compile.push(dep);
    } else if (scope === 'runtime') {
      categorized.runtime.push(dep);
    } else if (scope === 'test' || scope === 'testImplementation' || scope === 'androidTestImplementation') {
      categorized.test.push(dep);
    } else if (scope === 'provided') {
      categorized.provided.push(dep);
    } else if (scope === 'system') {
      categorized.system.push(dep);
    } else {
      categorized.other.push(dep);
    }
  }

  return categorized;
}

export async function JavaScanner(projectPath: string): Promise<ScannerResult | null> {
  try {
    let projectBuildType = 'unknown';

    // 先尝试作为Maven项目扫描
    let javaInfo = await scanMavenProject(projectPath);

    // 如果不是Maven项目，尝试作为Gradle项目扫描
    if (!javaInfo) {
      javaInfo = await scanGradleProject(projectPath);
      if (javaInfo) {
        projectBuildType = 'gradle';
      }
    } else {
      projectBuildType = 'maven';
    }

    if (!javaInfo) {
      return null;
    }

    // 计算项目大小
    const size = await folderSize.loose(projectPath);

    // 对依赖进行分类
    const categorizedDeps = categorizeDependencies(javaInfo.dependencies);

    // 创建基本信息列表
    const basicInfo = [
      {"名称": javaInfo.artifactId || path.basename(projectPath)},
      {"类型": "Java"},
      {"构建工具": projectBuildType},
      {"路径": projectPath},
      {"大小": FormatUtil.formatFileSize(size)},
      {"组ID": javaInfo.groupId},
      {"构件ID": javaInfo.artifactId},
      {"版本": javaInfo.version},
      {"编译依赖": categorizedDeps.compile.length},
      {"运行时依赖": categorizedDeps.runtime.length},
      {"测试依赖": categorizedDeps.test.length},
      {"provided依赖": categorizedDeps.provided.length},
      {"system依赖": categorizedDeps.system.length},
      {"其他依赖": categorizedDeps.other.length},
    ].filter(item => Object.values(item)[0] !== undefined);

    // 创建更多详细信息
    const mores = [
      {
        title: "编译依赖",
        type: "table" as const,
        list: categorizedDeps.compile.map(dep => ({
          groupId: dep.groupId,
          artifactId: dep.artifactId,
          version: dep.version,
          scope: dep.scope || 'compile'
        }))
      },
      {
        title: "运行时依赖",
        type: "table" as const,
        list: categorizedDeps.runtime.map(dep => ({
          groupId: dep.groupId,
          artifactId: dep.artifactId,
          version: dep.version,
          scope: dep.scope
        }))
      },
      {
        title: "测试依赖",
        type: "table" as const,
        list: categorizedDeps.test.map(dep => ({
          groupId: dep.groupId,
          artifactId: dep.artifactId,
          version: dep.version,
          scope: dep.scope
        }))
      },
      {
        title: "全部依赖",
        type: "table" as const,
        list: javaInfo.dependencies.map(dep => ({
          groupId: dep.groupId,
          artifactId: dep.artifactId,
          version: dep.version,
          scope: dep.scope || 'compile'
        }))
      }
    ];

    // 如果某类依赖为空，则从mores中移除
    const filteredMores = mores.filter(more => more.list.length > 0);

    return {
      projectName: javaInfo.artifactId || path.basename(projectPath),
      basicInfo,
      mores: filteredMores
    };
  } catch (error) {
    console.error(`扫描Java项目失败: ${projectPath}`, error);
    return null;
  }
}
